﻿using Autofac;
using Autofac.Integration.Mvc;
using KingsSharp.Common.Logging;
using KingsSharp.Core;
using KingsSharp.Core.Caching;
using KingsSharp.Core.Data;
using KingsSharp.Core.Data.Entity;
using KingsSharp.Core.Data.Entity.Migrations;
using CRM.Admin.Contracts.Contract.Sys;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Reflection;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;

namespace CRM.Admin
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start(object sender, EventArgs e)
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            LogManager.AddLoggerAdapter(new Log4NetLoggerAdapter());
            ICacheProvider provider = new RuntimeMemoryCacheProvider();
            CacheManager.SetProvider(provider, CacheLevel.First);

            Assembly[] assemblies = System.Web.Compilation.BuildManager.GetReferencedAssemblies()
           .Cast<Assembly>().ToArray();
            MapperRegisters.RegisterAll(assemblies);
            AutofacMvcRegister(assemblies);
            SeedActionInitialize(assemblies);
            DatabaseInitialize(assemblies);
            AdminInitialize();
        }
        protected void Session_Start(object sender, EventArgs e)
        {
            int a = 0;
        }
        protected void Session_End(object sender, EventArgs e)
        {
            int a = 0;
        }
        private void AutofacMvcRegister(params Assembly[] assemblyService)
        {
            ContainerBuilder builder = new ContainerBuilder();

            builder.RegisterType<DefualtDbContext>().InstancePerLifetimeScope();
            builder.RegisterGeneric(typeof(Repository<,>)).As(typeof(IRepository<,>));
            Type baseType = typeof(IDependency);
            Assembly[] assemblies = assemblyService;
            builder.RegisterAssemblyTypes(assemblies)
                .Where(type => baseType.IsAssignableFrom(type) && !type.IsAbstract)
                .AsImplementedInterfaces()
                .InstancePerLifetimeScope();
            builder.RegisterControllers(Assembly.GetExecutingAssembly()).AsSelf().PropertiesAutowired();
            builder.RegisterFilterProvider();
            IContainer container = builder.Build();
            AppVariable.IocContainer = container;
            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
        }
        private void DatabaseInitialize(params Assembly[] assemblyService)
        {
            Func<ICollection<Assembly>, string, Type[]> modelAssemblyRelation =
                (assemblys, connectionstring) =>
                {
                    Type[] types = assemblys.SelectMany(ass => ass.GetTypes()).ToArray();
                    return types;
                };
            DatabaseInitializer.AssemblyRelation = modelAssemblyRelation;

            DatabaseInitializer.DesConnectionString = connectionstring => { return KingsSharp.Common.Secutiry.DesHelper.Decrypt(connectionstring,AppConsts.DES_SQL_KEY); };

            Database.SetInitializer(new BaseDatabaseInitializer<DefualtDbContext,
              DefualtMigrationsConfiguration>());

            DatabaseInitializer.Initialize();
        }
        private void SeedActionInitialize(params Assembly[] assemblyService)
        {
            Type baseType = typeof(ISeedAction);
            Type[] types = assemblyService.SelectMany(a => a.GetTypes().Where
               (type => baseType.IsAssignableFrom(type) && baseType!= type)).ToArray();
            CreateDatabaseIfNotExistsWithSeed<DefualtDbContext>.SetSeedActionsType(typeof(DefualtDbContext), types);
        }
        /// <summary>
        /// init
        /// </summary>
        private void AdminInitialize()
        {
            var menuservice = AppVariable.IocContainer.Resolve<IMenuService>();

            var catalogs = menuservice.MenuCatalogs.Include(a => a.ParentMenuCatalog).Include(a => a.CataLogs).Where(a => a.IsDeleted == false).OrderBy(a => a.Order).ToList();
            foreach (var catalog in catalogs)
            {
                MenuItem.Instance.CatalogItems.Add(catalog);
            }

            var menunodes = menuservice.MenuNodes.Include(a => a.Actions).Where(a => a.IsDeleted == false).ToList();

            foreach (var menunode in menunodes)
            {
                MenuItem.Instance.MenuNodeItems.Add(menunode);
            }
        }
    }
}
